--
-- Author: ping.wang
-- Date: 2018-12-17 13:34:34
--
local fileName = string.getModeName(...)
local ClassRef = class(fileName)

local MOVE_SPEED = 300 --标量速度 不具有方向 1秒移动像素速度

function ClassRef:ctor(params)
	self._contentSize = params.size
	self._parentNode = params.parentNode
	self._subNodeClass = params.subNodeClass
	self._paddingLen = params.paddingLen or 0
	self._selectedCb = params.selectedCb

	local testSp = display.newScale9Sprite("public/public_black.png",0, 0, self._contentSize)
	testSp:setAnchorPoint(0,0)

	local clipNode = cc.ClippingNode:create()
	clipNode:setInverted(false)
	clipNode:setAlphaThreshold(1)
	clipNode:setStencil(testSp)
	clipNode:setName("di")
	clipNode:setAnchorPoint(0,0)
	clipNode:setPosition(0,0)
	clipNode:setContentSize(self._contentSize)
	self._parentNode:addChild(clipNode)

	local listener = cc.EventListenerTouchOneByOne:create()
	listener:setSwallowTouches(false)
	listener:registerScriptHandler(handler(self,self.onTouchBegan),cc.Handler.EVENT_TOUCH_BEGAN)
	listener:registerScriptHandler(handler(self,self.onTouchEnded),cc.Handler.EVENT_TOUCH_ENDED)
	listener:registerScriptHandler(handler(self,self.onTouchMoved),cc.Handler.EVENT_TOUCH_MOVED)
	listener:registerScriptHandler(handler(self,self.onTouchCancelled),cc.Handler.EVENT_TOUCH_CANCELLED)
	local eventDispatcher = self._parentNode:getEventDispatcher()
	eventDispatcher:addEventListenerWithSceneGraphPriority(listener, clipNode)

	clipNode:scheduleUpdate( handler(self, self.updateFrame))

	--初始化显示多少个node
	self._clippingNode = clipNode
	self._subNodeList = {} --显示的node需要放这里
end


--data = {{},{},{},{}}
--初始化的时候调用 平时不可以调用 首次显示调用
function ClassRef:setData(data,defaultSelectIdx)
	self._data = data --显示用的数据
	self._beginMove = 0 --记录一下当前移动的距离 要么是x要么是y
	if not defaultSelectIdx then defaultSelectIdx = 1 end

	self._clippingNode:removeAllChildren()
	self._subNodeList = {}

	if not self._data or #self._data == 0 then
		return
	end

	local startP = self._contentSize.height/2
	for k,v in ipairs(self._data) do
		local tempNode = self._subNodeClass.create()
		display.setCascadeOpacityEnabled(tempNode, true)
		tempNode:setData(v)
		if not self._subLen then
			self._subLen = tempNode:getContentSize().height
			self._nodePaddingLen = self._subLen + self._paddingLen
		end
		self:setNodePos(tempNode,0,startP)
		startP = startP - self._nodePaddingLen
		table.insert(self._subNodeList,tempNode)
		tempNode:onBtnClick(handler(self,self.clickMoveTo))
		self._clippingNode:addChild(tempNode)
	end

	--通过数据 给定了可以移动的范围
	self._minMove = 0
	self._maxMove = (#self._data - 1) * self._nodePaddingLen

	self._initSelectedIdx = 1
	self._moveDistance = (defaultSelectIdx - 1) * self._nodePaddingLen --重置移动距离
	self:_updateNodePosByMoveDis(0,0)
	self._beginMoveDis = 0

	if self._selectedCb then
		self._selectedCb(self._data[defaultSelectIdx])
	end
	self._curSelectedIdx = defaultSelectIdx

end

function ClassRef:clickMoveTo(subNode)
	if self._canClickSubNode then
		local posX,posY = subNode:getPosition()
		local startP = self._contentSize.height/2

		self:_startMove(startP - posY)
		self._canClickSubNode = false
	end
end

--设置节点的位置 同时要设置其缩放 以及 zorder
function ClassRef:setNodePos(node,posX,posY)
	node:setPosition(posX,posY)
	local referPos = self._contentSize.height/2
	local dt = math.abs(posY - referPos)
	dt = 2 * dt /(self._contentSize.height - self._subLen)
	if dt > 1 then dt = 1 end
	local maxScale = 1
	local minScale = 0.6
	local sc = maxScale - dt * dt * (maxScale - minScale)
	node:setScale(sc)
	if sc < 0.8 then
		local opc = 255 * math.abs(sc - 0.6) / 0.2
		node:setOpacity(opc)
	else
		node:setOpacity(255)
	end
	node:setLocalZOrder(100 - dt * 100)
end

function ClassRef:onTouchBegan(touch,event)
	--若没有数据 不用响应点击事件
	if not self._data or #self._data == 0 then return false end

	local locationX,locationY = touch:getLocation2()
	local size = self._parentNode:getContentSize()
	local pos = self._parentNode:convertToNodeSpace(cc.p(locationX,locationY))
	if pos.x >= 0 and pos.y >= 0 and pos.x <= size.width and pos.y <= size.height then
		self:_endMove()
		self._canClickSubNode = true
		self._startMoved = false
		self._beginTouchPoint = cc.p(locationX,locationY)
		return true
	end
	return false

end

function ClassRef:onTouchMoved(touch,event)

	local locationX,locationY = touch:getLocation2()
	local delta = touch:getDelta()
	self:_refreshContent(delta)
	--5像素内的移动不算移动 算点击
	if self._canClickSubNode and math.abs(self._beginTouchPoint.y - locationY) > 5 then
		self._canClickSubNode = false
		self._startMoved = true
	end

end

function ClassRef:onTouchCancelled(touch,event)
	--结束移动的时候调用调整节点位置的函数
	if self._startMoved then
		self:_adjustNodePos()
	end
end

function ClassRef:onTouchEnded(touch,event)
	--结束移动的时候调用调整节点位置的函数
	if self._startMoved then
		self:_adjustNodePos()
	end
end

--根据当前的移动总距离调整节点位置
function ClassRef:_adjustNodePos()
	local len = math.abs(self._moveDistance)% self._nodePaddingLen
	if len >= self._nodePaddingLen* 0.5 then
		len = self._nodePaddingLen - len
	else
		len = -len
	end

	self:_startMove(len)
end

--位移相对的一定得位置
function ClassRef:_startMove(moveDis)
	self._targetMoveDis = math.abs(moveDis)
	self._moveDirection = 1
	if moveDis < 0 then self._moveDirection = -1 end
	--在指定时间内移动moveDis长度
	self._canMove = true
	self._beginMoveDis = 0
end

function ClassRef:_refreshContent(pos)
	self:_updateNodePosByMoveDis(pos.x,pos.y)
end

function ClassRef:_updateNodePosByMoveDis(moveX,moveY)
	local distance = self._moveDistance + moveY
	if distance <= self._minMove then
		self._moveDistance = self._minMove
	elseif distance >=self._maxMove then
		self._moveDistance = self._maxMove
	else
		self._moveDistance = distance
	end

	local newPos = 0
	local startP = self._contentSize.height/2
	for i = 1,#self._subNodeList do
		local oldX,oldY = self._subNodeList[i]:getPosition()
		newPos = startP - (i - 1) * self._nodePaddingLen + self._moveDistance

		self:setNodePos(self._subNodeList[i],oldX,newPos)
	end
end

function ClassRef:_endMove()
	--结束的时候我们重新计算下moveDistance
	if self._moveDistance <= self._minMove then
		self._moveDistance = self._minMove
	elseif self._moveDistance >=self._maxMove then
		self._moveDistance = self._maxMove
	end

	self._curSelectedIdx = self:getSelectedIdx()

	if self._canMove then
		if self._selectedCb then
			self._selectedCb(self._data[self._curSelectedIdx])
		end
	end
	self._beginMoveDis = 0
	self._canMove = false
	self._targetMoveDis = nil
end

--获得当前选中的节点
--我们有一个初始化选中节点
--还有一个当前已经移动的distance distance>= -#self._data * self._nodePaddingLen and distance <=   #self._data * self._nodePaddingLen
function ClassRef:getSelectedIdx()
	if self._moveDistance == self._minMove then
		return self._initSelectedIdx
	end
	--todo 可能是around
	return self._initSelectedIdx + math.round(self._moveDistance/self._nodePaddingLen)
end

function ClassRef:updateFrame(dt)
	if not self._data or #self._data == 0 then
		return
	end

	if not self._canMove or not self._targetMoveDis then return end
	local s = dt * MOVE_SPEED --当前帧移动距离

	if self._beginMoveDis + s > self._targetMoveDis then
		s = self._targetMoveDis - self._beginMoveDis
		self._beginMoveDis = self._targetMoveDis
	else
		self._beginMoveDis = self._beginMoveDis + s
	end

	self:_updateNodePosByMoveDis(0,s * self._moveDirection)
	if self._beginMoveDis >= self._targetMoveDis then
		self:_endMove()
	end
end

function ClassRef:getAllNodes()
	return self._subNodeList
end

return ClassRef